---
description:
  Instrumenting Couchbase Lite for Debugging, Crash Reporting and Performance
  Profiling
---

# Instrumentation

The execution of certain operations can be traced through the tracing API. This
is useful for debugging and performance profiling.

CBL Dart has builtin trace points at which flow control is given to the
currently installed `api|TracingDelegate`.

Included in this package is the `api|DevToolsTracing` delegate, which records
timeline events that can be later visualized through the Dart DevTools
Performance Page.

You can install a delegate by calling `api|TracingDelegate.install`:

```dart
await TracingDelegate.install(DevToolsTracing());
```

## Sentry

The Sentry integration provided by `api|cbl_sentry|pkg:` installs a
`api|DevToolsTracing` to transparently record breadcrumbs and transaction spans.

### Features

- Record log messages as Sentry breadcrumbs
- Record CBL Dart API usage as Sentry breadcrumbs
- Record CBL Dart operations as Sentry transaction spans

### Limitations

Sentry currently does not support binding transaction spans to zones. This means
there can only be one global transaction span that integrations can
transparently access. To support more advanced use cases, this package provides
a mechanism to bind transaction spans to zones. This mechanism will be removed
if and when Sentry supports this natively.

### Getting started

1. Make sure your [app is setup](install.mdx) for using Couchbase Lite.

1. Add the `api|cbl_sentry|pkg:` package as a dependency:

   ```bash
   flutter pub add cbl_sentry
   ```

1. Add the `api|cbl_sentry|CouchbaseLiteIntegration` when configuring Sentry:

   ```dart
   import 'package:cbl_sentry/cbl_sentry.dart';
   import 'package:sentry/sentry.dart';

   void main() {
     Sentry.init(
       (options) {
         options
           ..dsn = ...
           // While testing your Sentry configuration, make sure that all traces are sampled.
           ..tracesSampleRate = 1
           // Add the CBL Dart integration.
           ..addIntegration(CouchbaseLiteIntegration());
       },
       appRunner: () async {
         runApp(MyApp());
       }
     );
   }
   ```

   To find out about configurable options, see the documentation of
   `api|cbl_sentry|CouchbaseLiteIntegration`.

   :::caution

   Make sure you don't install a `api|TracingDelegate` when using the
   `api|cbl_sentry|CouchbaseLiteIntegration`. The integration has to be able to
   install a `api|TracingDelegate` itself.

   :::

### Performance tracing

This integration only records transaction spans when a transaction has been
started and a child span of the transaction is available in the environment.

To find a span, the integration uses `api|cbl_sentry|fn:cblSentrySpan`. This is
a getter that returns either a span that has been bound to the current zone or
as a fallback the result of `api|sentry:sentry_io|Sentry.getSpan`. To bind a
span to a zone use `api|cbl_sentry|fn:runWithCblSentrySpan`.

The following code snippet shows functions that are useful to trace the
performance of operations in an app:

```dart
Future<T> runAppTransaction<T>(String name, Future<T> Function() fn) =>
    _runAppSpan(Sentry.startTransaction(name, 'task'), fn);

Future<T> runAppOperation<T>(String name, Future<T> Function() fn) =>
    _runAppSpan(cblSentrySpan!.startChild(name), fn);

Future<T> _runAppSpan<T>(ISentrySpan span,Future<T> Function() fn) async {
  try {
    return await runWithCblSentrySpan(span, fn);
    // ignore: avoid_catches_without_on_clauses
  } catch (e) {
    span
      ..throwable = e
      ..status = const SpanStatus.internalError();
    rethrow;
  } finally {
    span.status ??= const SpanStatus.ok();
    await span.finish();
  }
}
```

A app operation like the one below is traced as a transaction span, with CBL
Dart operations as child spans:

```dart
Future<void> queryDatabase() => runAppOperation('queryDatabase', () async {
      final query = await Query.fromN1ql(
        db,
        'SELECT * FROM example WHERE age >= 28 OR name LIKE "A%"',
      );
      final resultSet = await query.execute();
      final results = await resultSet
          .asStream()
          .map((result) => result.toPlainMap())
          .toList();

      prettyPrintJson(results);
    });
```

![Sentry Trace Example](https://github.com/cbl-dart/cbl-dart/blob/main/packages/cbl_sentry/doc/img/sentry-trace-example.png?raw=true)
